/**
 * 以accurate开头的函数返回的必定是string类型的数字
 */

import { BigNumber } from '../bigNumber';
import { isValidValue } from '../../index';

/**
 * 【推荐👍】准确取位
 * @param value {string | number}
 * @param [precision] {number|undefined}
 * @param [rm] {number|undefined}
 * @returns {string}
 */
const accurateToFixed = (value, precision, rm) => new BigNumber(value).toFixed(precision, rm);

/**
 * 【不建议使用】取位得到number （为number类型的最大精度）
 * @param value {string | number}
 * @param [precision] {number|undefined}
 * @returns {number}
 */
const toFixedGotNumber = (value, precision) => +new BigNumber(accurateToFixed(value, precision));

/**
 * 准确相加
 * @returns {string}
 */
const accuratePlus = (...args) => BigNumber.sum(...args).toFixed();

/**
 * 准确相减
 * @returns {string}
 */
const accurateMinus = (...args) =>
  args.reduce((sum, pre) => (isValidValue(pre) ? new BigNumber(sum) : new BigNumber(sum).minus(pre))).toFixed();

/**
 * 准确相乘
 * @returns {string}
 */
const accurate2NumTimes = (...args) =>
  args.reduce((sum, pre) => (isValidValue(pre) ? new BigNumber(sum) : new BigNumber(sum).times(pre))).toFixed();

/**
 * 准确相除
 * @returns {string}
 */
const accurate2NumDiv = (a, b) => new BigNumber(a).div(b).toFixed();

/**
 * 相加 并取位
 * @returns {number}
 */
const plusToFixed = (precision, ...args) => Number(accurateToFixed(accuratePlus(...args), precision));

/**
 * 相减 并取位
 * @returns {number}
 */
const minusToFixed = (precision, ...args) => Number(accurateToFixed(accurateMinus(...args), precision));

/**
 * 相乘 并取位
 * @returns {number}
 */
const numTimesToFixed = (precision, ...args) => Number(accurateToFixed(accurate2NumTimes(...args), precision));

/**
 * 相除 并取位
 * @returns {number}
 */
const numDivToFixed = (a, b, precision) => Number(accurateToFixed(accurate2NumDiv(a, b), precision));

/**
 * 缩写
 */
const aToFixed = accurateToFixed;
const aPlus = accuratePlus;
const aMinus = accurateMinus;
const aTimes = accurate2NumTimes;
const aDiv = accurate2NumDiv;

export {
  accurateToFixed,
  toFixedGotNumber,
  accuratePlus,
  accurateMinus,
  accurate2NumTimes,
  accurate2NumDiv,
  plusToFixed,
  minusToFixed,
  numTimesToFixed,
  numDivToFixed,
  aToFixed,
  aPlus,
  aMinus,
  aTimes,
  aDiv,
};
